/**
 * Copyright 2010 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
goog.provide('ccfa.admin');
goog.provide('ccfa.admin.plugin');

goog.require('goog.dom');
goog.require('goog.style');
goog.require('goog.editor.Command');
goog.require('goog.editor.Field');
goog.require('goog.editor.plugins.BasicTextFormatter');
goog.require('goog.editor.plugins.EnterHandler');
goog.require('goog.editor.plugins.HeaderFormatter');
goog.require('goog.editor.plugins.ListTabHandler');
goog.require('goog.editor.plugins.LoremIpsum');
goog.require('goog.editor.plugins.SpacesTabHandler');
goog.require('goog.editor.plugins.UndoRedo');
goog.require('goog.editor.plugins.RemoveFormatting');
goog.require('goog.ui.AnimatedZippy');
goog.require('goog.ui.editor.DefaultToolbar');
goog.require('goog.ui.editor.ToolbarController');
goog.require('goog.object');
goog.require('goog.ui.Component.EventType');
goog.require('goog.editor.Plugin');

/**
 * html editing plugin for our rich text editor.
 * @param {Element} textarea the textarea html form element that contains our
 *                  post.
 * @param {goog.ui.Toolbar} toolbar object
 * @constructor
 */
ccfa.admin.plugin.editHTML = function(textarea, toolbar) {
  goog.editor.Plugin.call(this);
  this.textarea = textarea;
  this.toolbar = toolbar;
};
goog.inherits(ccfa.admin.plugin.editHTML, goog.editor.Plugin);

/**
 * Trog class Id for this plugin.
 */
ccfa.admin.plugin.editHTML.prototype.getTrogClassId = function() {
  return 'editHTML';
};

/**
 * Command provided by this plugin.
 */
ccfa.admin.plugin.editHTML.COMMAND = {
  EDITHTML: 'editHtml'
};

/**
 * Commands supported by this plugin.
 * @private
 */
ccfa.admin.plugin.editHTML.SUPPORTED_COMMANDS_ =
  goog.object.transpose(ccfa.admin.plugin.editHTML.COMMAND);

/**
 * Responds true if a given command is supported by this plugin, otherwise
 * false.
 * @param {string} cmd the command being executed.
 * @return {Boolean} true if this plugin supports the command, otherwise false.
 */
ccfa.admin.plugin.editHTML.prototype.isSupportedCommand = function(cmd) {
  return cmd in ccfa.admin.plugin.editHTML.SUPPORTED_COMMANDS_;
};

/**
 * Hides the associated toolbar.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.hideToolbar_ = function() {
  this.toolbar.setVisible(false);
};

/**
 * Show the associated toolbar.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.showToolbar_ = function() {
  this.toolbar.setVisible(true);
};

/**
 * Hides the associated field object.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.hideFieldObject_ = function() {
  if (!goog.isDef(this.fieldObjectElement)) {
    this.fieldObjectElement = goog.dom.getElement(this.fieldObject.id);
  }
  goog.style.setStyle(this.fieldObjectElement, 'display', 'none');
};

/**
 * Show the field object.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.showFieldObject_ = function() {
  goog.style.setStyle(this.fieldObjectElement, 'display', '');
};

/**
 * Show the textarea input.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.showHTMLEditor_ = function() {
  goog.style.setStyle(this.textarea, 'display', '');
};

/**
 * Hide the textarea input.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.hideHTMLEditor_ = function() {
  goog.style.setStyle(this.textarea, 'display', 'none');
};

/**
 * Hides html editor buttons.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.hideHTMLEditorButtons_ = function() {
  goog.style.setStyle(this.HTMLEditor, 'display', 'none');
};

/**
 * Shows the html editor buttons.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.showHTMLEditorButtons_ = function() {
  goog.style.setStyle(this.HTMLEditor, 'display', '');
};

/**
 * Updates the field editor with the edited HTML.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.updateFieldObjectContent_ = function() {
  this.fieldObject.setHtml(false, this.textarea.value);
};

/**
 * Builds the HTML editor buttons. These are built the first time the user 
 * requests to edit the HTML, otherwise these buttons/elements are not created.
 * @private
 */
ccfa.admin.plugin.editHTML.prototype.buildHTMLEditorButtons_ = function() {
  if (!goog.isDef(this.HTMLEditor)) {
    var button = goog.dom.createDom(
      'input', {'type': 'button', 'value': 'Edit Text'});
    button.onclick = goog.bind(this.execCommandInternal, this);
    
    this.HTMLEditor = goog.dom.createDom(
      'div', {'class': 'goog-toolbar', 'id': this.getTrogClassId()}, button);

    goog.dom.insertSiblingBefore(this.HTMLEditor, this.toolbar.getElement());
  }
};

/**
 * Handles a user request for editing HTML or text.
 */
ccfa.admin.plugin.editHTML.prototype.execCommandInternal = function(cmd) {
  if (goog.style.getStyle(this.textarea, 'display') == 'none') {
    this.buildHTMLEditorButtons_();
    this.hideToolbar_();
    this.hideFieldObject_();
    this.showHTMLEditorButtons_();
    this.showHTMLEditor_();
  } else {
    this.updateFieldObjectContent_();  
    this.hideHTMLEditorButtons_();
    this.hideHTMLEditor_();
    this.showFieldObject_();
    this.showToolbar_();
  }  
};

/**
 * CCFA Toolbar constructor.
 * @constructor
 */
ccfa.admin.toolbar = function(editorToolbarId, editorId, formInputId) {
  this.editorToolbar = goog.dom.getElement(editorToolbarId);
  this.formInput = goog.dom.getElement(formInputId);
  this.editor = new goog.editor.Field(editorId);
};

/**
 * Sets the Editors contents to match what is stored in the form element
 * associated with this toolbar.
 */
ccfa.admin.toolbar.prototype.setContent = function() {
    this.editor.injectContents(this.formInput.value,
                               goog.dom.getElement(this.editor.id));
};

/**
 * Closure plugins used by this toolbar.
 */
ccfa.admin.toolbar.TOOLBAR_PLUGINS = {
  'BasicTextFormatter': '',
  'UndoRedo': '',
  'ListTabHandler': '',
  'SpacesTabHandler': '',
  'EnterHandler': '',
  'HeaderFormatter': '',
  'RemoveFormatting': '',
  'LoremIpsum': 'Click to edit!'
};

/**
 * Registers the plugins with the field editor.
 */
ccfa.admin.toolbar.prototype.registerPlugins = function() {
  var plugins = ccfa.admin.toolbar.TOOLBAR_PLUGINS;
  for (var plugin in plugins) {
    this.editor.registerPlugin(
      new goog.editor.plugins[plugin](plugins[plugin]));
  }
  this.editor.registerPlugin(new ccfa.admin.plugin.editHTML(this.formInput,
                                                            this.toolbar));
};

/**
 * Closure buttons used by this toolbar.
 */
ccfa.admin.toolbar.TOOLBAR_BUTTONS = [
    goog.editor.Command.BOLD,
    goog.editor.Command.ITALIC,
    goog.editor.Command.UNDERLINE,
    goog.editor.Command.STRIKE_THROUGH,
    goog.editor.Command.FONT_SIZE,
    goog.editor.Command.FONT_COLOR,
    goog.editor.Command.BACKGROUND_COLOR,
    goog.editor.Command.JUSTIFY_LEFT,
    goog.editor.Command.JUSTIFY_CENTER,
    goog.editor.Command.JUSTIFY_RIGHT,
    goog.editor.Command.INDENT,
    goog.editor.Command.OUTDENT,
    goog.editor.Command.UNORDERED_LIST,
    goog.editor.Command.ORDERED_LIST,
    goog.editor.Command.REMOVE_FORMAT,
    goog.editor.Command.UNDO,
    goog.editor.Command.REDO,
    goog.editor.Command.EDIT_HTML
];

/**
 * Makes the editor editable.
 */
ccfa.admin.toolbar.prototype.enableToolbar = function() {
  this.editor.makeEditable();
};

/**
 * Updates the form input to match the copy created inside the editor.
 */
ccfa.admin.toolbar.prototype.updateBodyInput = function() {
  this.formInput.value = this.editor.getCleanContents();
};

/**
 * Attaches listeners to the editor,
 */
ccfa.admin.toolbar.prototype.attachListeners = function() {
  goog.events.listen(this.editor,
                     goog.editor.Field.EventType.DELAYEDCHANGE,
                     goog.bind(this.updateBodyInput, this));
};

/**
 * Hides the HTML form input that stores the raw HTML of the copy.
 */
ccfa.admin.toolbar.prototype.hideFormInput = function() {
  goog.style.setStyle(this.formInput, 'display', 'none');
};

/**
 * Constructs our toolbar and hooks it up to a contoller.
 */
ccfa.admin.toolbar.prototype.constructToolbar = function() {
  this.toolbar = goog.ui.editor.DefaultToolbar.makeToolbar(
    ccfa.admin.toolbar.TOOLBAR_BUTTONS, this.editorToolbar);
  new goog.ui.editor.ToolbarController(this.editor, this.toolbar);
  this.hideFormInput();
};

/**
 * Creates animated zippies.
 */
ccfa.admin.makeZippies = function(zippies) {
  for (var i = 0, zippy; zippy = zippies[i]; i++) {
    var headerId = zippy.id;
    var contentId = headerId + '-content';
    var zip = new goog.ui.AnimatedZippy(headerId, contentId, false);
  } 
};

/**
 * Sets up JavaScript UI elements used on a page.
 */
ccfa.admin.initializePage = function() {
  if (window.location.search) {  // Create a toolbar and editor
    var toolbar = new ccfa.admin.toolbar('content-editor-toolbar',
                                         'content-editor',
                                         'body');
    toolbar.constructToolbar();
    toolbar.attachListeners();
    toolbar.registerPlugins();
    toolbar.setContent();
    toolbar.enableToolbar();
    
  }

  // Create animated zippies.  
  var animatedZippies = goog.dom.getElementsByTagNameAndClass(
    '', 'animated-zippy');
  if (animatedZippies.length) {
    ccfa.admin.makeZippies(animatedZippies);
  }
};

// Setup our page with the UI elements.
ccfa.admin.initializePage();